from typing import Type
from textual.app import App, ComposeResult
from textual.driver import Driver
from textual.widgets import (
    Input, 
    ListView, 
    ListItem, 
    TextArea, 
    Header, 
    Footer, 
    Select, 
    SelectionList, 
    Digits,
    Label,
    Markdown,
    Static
)
from textual.widget import Widget
from textual.containers import (
    Vertical, 
    VerticalScroll, 
    Horizontal, 
    Container,
    Center
)
from textual import on, work
from rich.syntax import Syntax

from core.xmake import XmakeRepo, XmakeRepoAnalyzer

from textual.screen import Screen, ModalScreen


class XmakeScreen(Screen):

    BINDINGS = [
        ('l', 'local', 'Local Packages'),
        ('x', 'xrepo', 'Official Packages'),
        ('b', 'artifacts', 'Official Artifacts'),
    ]
    
    def action_local(self):
        ''''''
        self.app.push_screen(LocalScreen(self.xmake))

    def action_xrepo(self):
        self.app.push_screen(XrepoScreen(self.xmake))

    def action_artifacts(self):
        self.app.push_screen(ArtifactsScreen(self.xmake))

class LocalScreen(XmakeScreen):
    '''本地已安装窗口'''
    
    CSS_PATH = "app.css"

    def __init__(self, xmake: XmakeRepoAnalyzer):
        super().__init__()
        self.xmake = xmake

    def compose(self) -> ComposeResult:
        yield Header()
        with Vertical():
            with Horizontal():
                with Vertical(classes="options"):
                    yield Select(
                        [], id="packages", prompt="选择包"# allow_blank=False
                    )
                    yield Select(
                        [], id="versions", prompt="选择版本"# allow_blank=False
                    )
                    yield Static('@学不会 xmake 的屑', classes='me')
                with Vertical():
                    yield Markdown()
                    yield TextArea.code_editor(id="view", language='json', read_only=True)
        yield Footer()

    def on_mount(self) -> None:
        s_pkgs = self.query_one('#packages', Select)
        s_pkgs.border_title = '选择包'
        pkgs = [pkg for pkg in self.xmake.pkgs()]
        s_pkgs.set_options(
            [(pkg, pkg) for pkg in pkgs]
        )
        s_pkgs.value = pkgs[0]
    
    @on(Select.Changed, '#packages')
    def package_changed(self, event: Select.Changed):
        s_vers = self.query_one('#versions', Select)
        s_vers.border_title = '选择版本'

        vers = [ver for ver in self.xmake.get_pkg_versions(event.value)]
        s_vers.set_options(
            [(ver, ver) for ver in vers]
        )
        s_vers.value = vers[0]

    @on(Select.Changed, '#versions')
    def version_changed(self, event: Select.Changed):
            s_pkgs = self.query_one('#packages', Select)
            s_vers = self.query_one('#versions', Select)

            name = s_pkgs.value
            ver  = s_vers.value
            pkg = self.xmake.get_pkg(name, ver)

            if 'version' not in pkg:
                self.notify('没有数据，请完整安装该包', severity="warning", timeout=1.5)
                return

            self.query_one(Markdown).update(f'''\
### {name}@{ver}

> 版本: {pkg['version']}  
> 描述: {pkg['description']}  
> 链接: {self.xmake.help_get_pkg_homepage(name)}  
''')
            import json
            view = self.query_one(TextArea)
            view.language = 'json'
            view.load_text(json.dumps(pkg, indent=2))


class XrepoScreen(XmakeScreen):
    '''官方包窗口'''
    
    CSS_PATH = "app.css"

    def __init__(self, xmake: XmakeRepoAnalyzer):
        super().__init__()
        self.xmake = xmake

    def compose(self) -> ComposeResult:
        yield Header()
        with Vertical():
            with Horizontal():
                with Vertical(classes="options"):
                    yield Select(
                        [], id="packages", prompt="选择包"# allow_blank=False
                    )
                    yield Input(id='search', placeholder='输入关键字')
                    with Container():
                        yield ListView(id='listpkgs')
                with Vertical():
                    yield Markdown()
                    yield TextArea.code_editor(id="view", read_only=True)
        yield Footer()

    class PkgItem(ListItem):

        def __init__(self, pkgname: str):
            self.pkgname = pkgname
            super().__init__(Label(pkgname))

    def on_mount(self) -> None:
        s_pkgs = self.query_one('#packages', Select)
        s_pkgs.border_title = '选择包'
        pkgs = [pkg for pkg in self.xmake.repo_pkgs()]
        pkgs.sort()
        s_pkgs.set_options(
            [(pkg, pkg) for pkg in pkgs]
        )
        s_pkgs.value = pkgs[0]

        listpkgs = self.query_one('#listpkgs', ListView)
        for pkg in pkgs:
            listpkgs.append(XrepoScreen.PkgItem(pkg))

        self.query_one(Input).border_title = '搜索'
        self.query_one(Input).focus()
        self.query_one(Container).border_title = 'xrepo 包列表'
        s_pkgs.add_class('hide')
        # self.query_one(TextArea).focusable = False


    def on_input_submitted(self, event: Input.Submitted):
        search = event.value
        listpkgs = self.query_one(ListView)
        self.filter(search, listpkgs)

    # @work(thread=True)
    def filter(self, search: str, listpkgs: ListView):
        for node in listpkgs._nodes:
            item: XrepoScreen.PkgItem = node
            if search.lower() in item.pkgname.lower():
                item.remove_class('hide')
                # self.app.call_from_thread(item.remove_class, 'hide')
            else:
                item.add_class('hide')
                # self.app.call_from_thread(item.add_class, 'hide')
    
    @on(ListView.Selected, '#listpkgs')
    def pkg_selected(self, event: ListView.Selected):
        pkg: XrepoScreen.PkgItem = event.item
        self.package_changed(Select.Changed(None, value=pkg.pkgname))


    @on(Select.Changed, '#packages')
    def package_changed(self, event: Select.Changed):
        name = event.value

        pkg = self.xmake.get_repo_pkg(name)
        self.query_one(Markdown).update(f'''\
### {name}
    
> 候选版本: {self.xmake.help_get_pkg_versions(name)}  
> 描述: {self.xmake.help_get_pkg_description(name)}  
> 链接: {self.xmake.help_get_pkg_homepage(name)}  
''')
        view = self.query_one(TextArea)
        # from tree_sitter import Language, Parser
        # from tree_sitter_languages import get_language
        # from pathlib import Path

        # lua_language = get_language('lua')
        # TODO: tree-sitter ADT 语法树
        # https://weakptr.site/posts/2021-07-29-wan-wan-tree-sitter/


        # https://textual.textualize.io/widgets/text_area/#adding-support-for-custom-languages
        # lua_highlight_query = (Path(__file__).parent / 'highlights.scm').read_text()
        # https://github.com/tree-sitter/tree-sitter-java/blob/master/queries/highlights.scm
        # https://github.com/tree-sitter/tree-sitter-java/blob/ac14b4b1884102839455d32543ab6d53ae089ab7/queries/highlights.scm
# 
        # view.register_language(lua_language, lua_highlight_query)
        # view.language = 'lua'

        view.load_text(pkg)

class ArtifactsScreen(XmakeScreen):
    '''制品窗口'''
    
    CSS_PATH = "app.css"

    def __init__(self, xmake: XmakeRepoAnalyzer):
        super().__init__()
        self.xmake = xmake

    def compose(self) -> ComposeResult:
        yield Header()
        with Vertical():
            with Horizontal():
                with Vertical(classes="options"):
                    yield Select(
                        [], id="packages", prompt="选择制品"# allow_blank=False
                    )
                    yield Select(
                        [], id="versions", prompt="选择版本"# allow_blank=False
                    )
                with Vertical():
                    yield Markdown()
                    yield TextArea.code_editor(id="view", language='json', read_only=True)
        yield Footer()

    def on_mount(self) -> None:
        s_pkgs = self.query_one('#packages', Select)
        pkgs = [pkg for pkg in self.xmake.repo_artifacts()]
        s_pkgs.set_options(
            [(pkg, pkg) for pkg in pkgs]
        )
        s_pkgs.value = pkgs[0]
    
    @on(Select.Changed, '#packages')
    def package_changed(self, event: Select.Changed):
        s_vers = self.query_one('#versions', Select)
        vers = [ver for ver in self.xmake.get_artifact_versions(event.value)]
        s_vers.set_options(
            [(ver, ver) for ver in vers]
        )
        s_vers.value = vers[0]

    @on(Select.Changed, '#versions')
    def version_changed(self, event: Select.Changed):
            s_pkgs = self.query_one('#packages', Select)
            s_vers = self.query_one('#versions', Select)

            name = s_pkgs.value
            ver  = s_vers.value
            artifact = self.xmake.get_artifact(name, ver)
            self.query_one(Markdown).update(f'''\
### {name}
''')
            import json
            view = self.query_one(TextArea)
            view.language = 'json'
            view.load_text(json.dumps(artifact, indent=2))

class XmakeApp(App):    

    CSS_PATH = "app.css"

    def __init__(self):
        super().__init__()
        self.is_load = False

    def compose(self) -> ComposeResult:
        yield Header()
        with Vertical():
            with Center():
                yield Static('初始化中', classes='init')
        yield Footer()
    
    def on_mount(self) -> None:
        if not self.is_load:
            self.notify(title='初始化', message='正在初始化...', timeout=0.5)
            self.loadxmake()
    
    @work(thread=True)
    def loadxmake(self):
        self.is_load = True
        self.xmake = XmakeRepoAnalyzer()
        self.call_from_thread(self.xmake_loaded)

    def xmake_loaded(self):
        ''''''
        self.push_screen(LocalScreen(self.xmake))


if __name__ == "__main__":

    app = XmakeApp()
    app.run()